#include "app.h"

#include <stdio.h>
#include <vector>

#include <esp_log.h>

#include "board.h"

#include "esp_task_manager.h"
#include "mqtt_manager.h"
#include "logger_app.h" 
#include "relay_app.h"
#include "settings.h"
#include "system_info.h"
#include "config.h"

/*
 * ╔══════════════════════════════════════════════════════════════════════════════╗
 * ║                            LED状态指示总览                                   ║
 * ╚══════════════════════════════════════════════════════════════════════════════╝
 * 
 * 🎨 LED颜色和效果说明：
 * 
 * 📍 正常状态：
 * • kDeviceStateIdle          - 蓝色常亮      - 系统正常工作
 * • kDeviceStateStarting      - 紫色呼吸灯(30ms周期)  - 应用启动中
 * • kDeviceStateHardwareInit  - 白色呼吸灯(40ms周期)  - 硬件初始化中
 * • kDeviceStateHardwareOk    - 绿色常亮      - 硬件初始化成功
 * • kDeviceStateConnecting    - 绿色呼吸灯(50ms周期)  - 网络连接中
 * • kDeviceStateNetworkOk     - 绿色常亮      - 网络连接成功
 * • kDeviceStateMqttConnecting- 青色呼吸灯(60ms周期)  - MQTT连接中
 * • kDeviceStateMqttOk        - 青色常亮      - MQTT连接成功
 * • kDeviceStateOta           - 无LED指示     - OTA检查中（后台进行）
 * • kDeviceStateOtaWrite      - 青色呼吸灯(60ms周期)  - ⚡ OTA写入中（重启类最终状态）
 * 
 * ⚠️ 错误状态：
 * • kDeviceStateHardwareError - 红色快闪(50ms)   - 硬件故障
 * • kDeviceStateNetworkError  - 红色慢闪(800ms)    - 网络连接失败
 * • kDeviceStateMqttError     - 黄色快闪(50ms)     - MQTT连接失败
 * • kDeviceStateOtaError      - 紫色慢闪(800ms)    - OTA更新失败
 * • kDeviceStateWifiConfig    - 粉色中闪(300ms)    - ⚡ WiFi配网模式（重启类最终状态）
 * • kDeviceStateUnknown       - 红色常亮          - 未知状态
 * • kDeviceStateError         - 轮换显示所有存在的错误类型
 *   - ERROR_HARDWARE          - 红色快闪(50ms) - 显示5秒
 *   - ERROR_WIFI              - 红色慢闪(800ms) - 显示5秒  
 *   - ERROR_MQTT              - 黄色快闪(50ms) - 显示5秒
 *   - ERROR_OTA               - 紫色慢闪(800ms) - 显示5秒
 *   注：多错误时按优先级轮换显示，每种错误显示5秒后切换到下一种
 * 
 * 🎯 状态转换流程：
 * 启动: Unknown → Starting → HardwareInit → HardwareOk/Error
 * 网络: Connecting → NetworkOk/Error → WifiConfig(如果失败，⚡重启类最终状态)
 * MQTT: MqttConnecting → MqttOk/Error
 * OTA: Ota(无LED) → OtaWrite(青色呼吸灯，⚡重启类最终状态) → 成功(重启)/OtaError
 * 完成: Idle(正常) / Error(有错误)
 * 
 * 📊 LED时间间隔分类：
 * • 超快闪 - 50ms   (严重错误)
 * • 中闪   - 300ms  (配网模式)
 * • 慢闪   - 800ms  (一般错误)
 * • 呼吸灯 - 30-60ms (正常过程)
 * 
 * ⚡ 重启类最终状态说明：
 * • kDeviceStateWifiConfig：配网完成后触发重启，系统重新初始化
 * • kDeviceStateOtaWrite：固件写入完成后自动重启，加载新固件
 * • 这两种状态下不再进行其他状态转换，系统等待重启
 */

// 日志标签
#define TAG "App"

static const char* const STATE_STRINGS[] = {
  "unknown",        // 0 - kDeviceStateUnknown
  "starting",       // 1 - kDeviceStateStarting 
  "hw_init",        // 2 - kDeviceStateHardwareInit
  "hw_error",       // 3 - kDeviceStateHardwareError
  "hw_ok",          // 4 - kDeviceStateHardwareOk
  "connecting",     // 5 - kDeviceStateConnecting
  "wifi_config",    // 6 - kDeviceStateWifiConfig
  "net_error",      // 7 - kDeviceStateNetworkError
  "net_ok",         // 8 - kDeviceStateNetworkOk
  "mqtt_connecting",// 9 - kDeviceStateMqttConnecting
  "mqtt_error",     // 10 - kDeviceStateMqttError
  "mqtt_ok",        // 11 - kDeviceStateMqttOk
  "ota",            // 12 - kDeviceStateOta
  "ota_write",      // 13 - kDeviceStateOtaWrite
  "ota_error",      // 14 - kDeviceStateOtaError
  "idle",           // 15 - kDeviceStateIdle
  "error"           // 16 - kDeviceStateError
};

// 构造函数
App::App() {
    ESP_LOGI(TAG,"应用初始化");
    event_group_ = xEventGroupCreate();
    auto& task_manager = TaskManager::GetInstance();
    led_task_executor_ = task_manager.CreateExecutor("led", 4096, 2, 0);
    main_task_executor_ = task_manager.CreateExecutor("main", 4096, 4, 0);
}

// 析构函数
App::~App() {
    ESP_LOGI(TAG,"应用销毁");
    vEventGroupDelete(event_group_);
}

// 启动应用
void App::Start() {
    SetDeviceState(kDeviceStateStarting);
        // 新增：初始化日志捕获
    LoggerApp::GetInstance().InitializeLogCapture();
    // 获取单例板级对象
    auto& board = Board::GetInstance();

    // Settings settings("mqtt", true);
    // settings.SetString("endpoint","110.41.147.192");
    // settings.SetString("client_id",SystemInfo::GetMacAddress());

    //硬件初始化
    board.Start();

    // 网络连接阶段
    board.StartNetwork();


    //MQTT连接
    MqttManager::GetInstance().start();
    {//依赖MQTT的模块
        //日志记录
        LoggerApp::GetInstance().start();
        //继电器控制
        RelayApp::GetInstance().start();
    }

    // 标记初始化完成
    is_initialization_complete_ = true;
    // 根据整体状态设置最终状态
    if (HasError()) {
        SetDeviceState(kDeviceStateError);
        ESP_LOGW(TAG, "系统启动完成，但存在错误: 0x%04X", GetErrorFlags());
    } else {
        SetDeviceState(kDeviceStateIdle);
        ESP_LOGI(TAG, "系统启动完成，所有功能正常");
    }
}

void App::SetError(ErrorFlags flag) {
    uint16_t old_flags = error_flags_;
    error_flags_ |= flag;  // 设置对应位
    
    if (old_flags != error_flags_) {
        ESP_LOGW(TAG, "设置错误标志: 0x%04X -> 0x%04X", old_flags, error_flags_);
    }
}

void App::ClearError(ErrorFlags flag) {
    uint16_t old_flags = error_flags_;
    error_flags_ &= ~flag;  // 清除对应位
    
    if (old_flags != error_flags_) {
        ESP_LOGI(TAG, "清除错误标志: 0x%04X -> 0x%04X", old_flags, error_flags_);
    }
}

void App::ClearAllErrors() {
    if (error_flags_ != ERROR_NONE) {
        ESP_LOGI(TAG, "清除所有错误标志: 0x%04X -> 0x0000", error_flags_);
        error_flags_ = ERROR_NONE;
    }
}

void App::SetDeviceState(DeviceState state) {
    main_task_executor_->AddTask([this, state]() {
        this->SetDeviceStateInternal(state);
    }, TaskType::IMMEDIATE, TaskPriority::TASKNORMAL, "set_device_state");
}

void App::SetDeviceStateInternal(DeviceState state) {
    if (device_state_ == state) {
        return;
    }
    
    ESP_LOGI(TAG, "状态变更: %s -> %s", STATE_STRINGS[device_state_], STATE_STRINGS[state]);

    if(device_state_ == kDeviceStateOtaWrite || device_state_ == kDeviceStateWifiConfig){
        ESP_LOGW(TAG,"上个状态是ota写入或配网,不用再设置状态,因为会重启");
        return;
    }
    
    // 根据设备状态进行错误标志位的加减操作
    switch (state) {
        case kDeviceStateIdle:
            ESP_LOGI(TAG, "设备进入正常工作状态");
            // 进入空闲状态表示系统运行正常，清除所有错误
            ClearAllErrors();
            break;
            
        case kDeviceStateStarting:
            ESP_LOGI(TAG, "应用启动中...");
            // 启动时清除所有错误（重新开始）
            ClearAllErrors();
            break;
            
        case kDeviceStateHardwareInit:
            ESP_LOGI(TAG, "硬件初始化中...");
            // 硬件初始化阶段，暂时清除硬件错误（准备重新检测）
            ClearError(ERROR_HARDWARE);
            break;
            
        case kDeviceStateHardwareOk:
            ESP_LOGI(TAG, "硬件初始化完成");
            // 硬件初始化成功，清除硬件错误
            ClearError(ERROR_HARDWARE);
            break;
            
        case kDeviceStateHardwareError:
            ESP_LOGE(TAG, "硬件错误");
            SetError(ERROR_HARDWARE);
            break;
            
        case kDeviceStateConnecting:
            ESP_LOGI(TAG, "正在连接网络...");
            // 开始连接时，清除网络相关错误（准备重新尝试）
            ClearError(ERROR_WIFI);
            break;
            
        case kDeviceStateWifiConfig:
            ESP_LOGI(TAG, "WiFi配网模式");
            // 进入配网模式，设置WiFi错误标志
            SetError(ERROR_WIFI);
            break;
            
        case kDeviceStateNetworkOk:
            ESP_LOGI(TAG, "网络连接成功");
            // 网络连接成功，清除WiFi错误
            ClearError(ERROR_WIFI);
            break;
            
        case kDeviceStateNetworkError:
            ESP_LOGE(TAG, "网络连接错误");
            // 记录错误
            LoggerApp::GetInstance().RecordWifiError();
            SetError(ERROR_WIFI);
            break;
            
        case kDeviceStateMqttConnecting:
            ESP_LOGI(TAG, "正在连接MQTT服务器...");
            // 开始MQTT连接时，清除MQTT错误（准备重新尝试）
            ClearError(ERROR_MQTT);
            break;
            
        case kDeviceStateMqttOk:
            ESP_LOGI(TAG, "MQTT连接成功");
            // MQTT连接成功，清除MQTT错误
            ClearError(ERROR_MQTT);
            break;
            
        case kDeviceStateMqttError:
            ESP_LOGE(TAG, "MQTT连接错误");
            // 记录错误
            LoggerApp::GetInstance().RecordMqttError();
            SetError(ERROR_MQTT);
            break;
            
        case kDeviceStateOta:
            ESP_LOGI(TAG, "OTA更新中...");
            // 记录OTA尝试
            LoggerApp::GetInstance().RecordOtaAttempt();
            // OTA过程中清除OTA错误标志
            ClearError(ERROR_OTA);
            break;
        case kDeviceStateOtaWrite:
            ESP_LOGI(TAG, "OTA写入中");
            break;
        case kDeviceStateOtaError:
            ESP_LOGE(TAG, "OTA更新失败");
            // 记录错误
            LoggerApp::GetInstance().RecordOtaError();
            SetError(ERROR_OTA);
            break;
            
        case kDeviceStateError:
            ESP_LOGE(TAG, "系统处于错误状态");
            // 错误状态不修改具体错误标志，保持现有错误信息
            break;

        case kDeviceStateUnknown:
        default:
            ESP_LOGW(TAG, "设备状态未知或无效");
            break;
    }
    last_device_state_=device_state_;
    device_state_ = state;
    
    //根据设备状态更新LED显示
    ShowDeviceStateOnLed();
    
    // 检查并设置最终状态
    CheckAndSetFinalState();
}

// 检查并设置最终状态（error/idle）
void App::CheckAndSetFinalState() {
    // 如果初始化未完成，不进行最终状态判断
    if (!is_initialization_complete_) {
        return;
    }
    
    // 如果当前已经是最终状态，避免重复设置
    if (device_state_ == kDeviceStateError || device_state_ == kDeviceStateIdle || device_state_ == kDeviceStateWifiConfig || device_state_ == kDeviceStateOtaWrite) {
        return;
    }
    
    // 使用SetDeviceState确保状态管理一致性
    if (HasError()) {
        ESP_LOGW(TAG, "检测到错误，设置为错误状态");
        SetDeviceState(kDeviceStateError);
    } else {
        ESP_LOGI(TAG, "无错误标志，设置为空闲状态");
        SetDeviceState(kDeviceStateIdle);
    }
}

void App::ShowDeviceStateOnLed() {
    auto* ws2812 = Board::GetInstance().GetWS2812();

    // 如果WS2812不可用，无法显示LED状态
    if (!ws2812) {
        return;
    }

    ESP_LOGI("LED", "设置LED状态 - 设备状态: %s, 错误标志: 0x%04X", STATE_STRINGS[device_state_], error_flags_);

    // 根据设备状态显示对应的LED效果
    switch (device_state_) {
        case kDeviceStateIdle:
            // 清除所有错误LED相关任务
            led_task_executor_->RemoveAllTasksByName("led_error");
            led_task_executor_->RemoveAllTasksByName("led_ok");
            // 正常工作状态 - 蓝色常亮
            led_task_executor_->AddTask([ws2812]() {
                ws2812->SetBrightness(80);
                ws2812->SetPixel(0, WS2812::Color::BLUE);
            }, TaskType::IMMEDIATE, TaskPriority::TASKNORMAL, "led_ok");
            break;
            
        case kDeviceStateStarting:
            // 清除所有LED相关任务
            led_task_executor_->RemoveAllTasksByName("led_error");
            led_task_executor_->RemoveAllTasksByName("led_ok");
            // 启动中 - 紫色呼吸灯
            led_task_executor_->AddPeriodicTask([ws2812]() {
                static uint8_t brightness = 5;
                static int8_t direction = 4;
                
                brightness += direction;
                if (brightness >= 50) {
                    brightness = 50;
                    direction = -4;
                } else if (brightness <= 5) {
                    brightness = 5;
                    direction = 4;
                }
                
                ws2812->SetBrightness(brightness);
                ws2812->SetPixel(0, WS2812::Color::PURPLE);
            }, std::chrono::milliseconds(30), TaskPriority::TASKNORMAL, "led_ok");
            break;
            
        case kDeviceStateHardwareInit:
            // 清除所有LED相关任务
            led_task_executor_->RemoveAllTasksByName("led_error");
            led_task_executor_->RemoveAllTasksByName("led_ok");
            // 硬件初始化中 - 白色呼吸灯
            led_task_executor_->AddPeriodicTask([ws2812]() {
                static uint8_t brightness = 5;
                static int8_t direction = 4;
                
                brightness += direction;
                if (brightness >= 50) {
                    brightness = 50;
                    direction = -4;
                } else if (brightness <= 5) {
                    brightness = 5;
                    direction = 4;
                }
                
                ws2812->SetBrightness(brightness);
                ws2812->SetPixel(0, WS2812::Color::WHITE);
            }, std::chrono::milliseconds(40), TaskPriority::TASKNORMAL, "led_ok");
            break;
            
        case kDeviceStateHardwareOk:
            // 清除所有LED相关任务
            led_task_executor_->RemoveAllTasksByName("led_error");
            led_task_executor_->RemoveAllTasksByName("led_ok");
            // 硬件初始化完成 - 绿色常亮
            led_task_executor_->AddTask([ws2812]() {
                ws2812->SetBrightness(80);
                ws2812->SetPixel(0, WS2812::Color::GREEN);
            }, TaskType::IMMEDIATE, TaskPriority::TASKNORMAL, "led_ok");
            break;
            
        case kDeviceStateHardwareError:
            break;
            
        case kDeviceStateConnecting:
            // 清除所有LED相关任务
            led_task_executor_->RemoveAllTasksByName("led_error");
            led_task_executor_->RemoveAllTasksByName("led_ok");
            // 网络连接中 - 绿色呼吸灯
            led_task_executor_->AddPeriodicTask([ws2812]() {
                static uint8_t brightness = 5;
                static int8_t direction = 4;
                
                brightness += direction;
                if (brightness >= 50) {
                    brightness = 50;
                    direction = -4;
                } else if (brightness <= 5) {
                    brightness = 5;
                    direction = 4;
                }
                
                ws2812->SetBrightness(brightness);
                ws2812->SetPixel(0, WS2812::Color::GREEN);
            }, std::chrono::milliseconds(50), TaskPriority::TASKNORMAL, "led_ok");
            break;
            
        case kDeviceStateWifiConfig:
            // 清除所有LED相关任务
            led_task_executor_->RemoveAllTasksByName("led_error");
            led_task_executor_->RemoveAllTasksByName("led_ok");
            // WiFi配网模式 - 粉色中速闪烁
            led_task_executor_->AddPeriodicTask([ws2812]() {
                static bool led_on = false;
                ws2812->SetBrightness(led_on ? 90 : 0);
                ws2812->SetPixel(0, led_on ? WS2812::Color::PINK : WS2812::Color::BLACK);
                led_on = !led_on;
            }, std::chrono::milliseconds(300), TaskPriority::TASKNORMAL, "led_ok");
            break;
            
        case kDeviceStateNetworkOk:
            // 清除所有LED相关任务
            led_task_executor_->RemoveAllTasksByName("led_error");
            led_task_executor_->RemoveAllTasksByName("led_ok");
            // 网络连接成功 - 绿色常亮
            led_task_executor_->AddTask([ws2812]() {
                ws2812->SetBrightness(80);
                ws2812->SetPixel(0, WS2812::Color::GREEN);
            }, TaskType::IMMEDIATE, TaskPriority::TASKNORMAL, "led_ok");
            break;
            
        case kDeviceStateNetworkError:
            break;
            
        case kDeviceStateMqttConnecting:
            // 清除所有LED相关任务
            led_task_executor_->RemoveAllTasksByName("led_error");
            led_task_executor_->RemoveAllTasksByName("led_ok");
            // MQTT连接中 - 青色呼吸灯
            led_task_executor_->AddPeriodicTask([ws2812]() {
                static uint8_t brightness = 5;
                static int8_t direction = 4;
                
                brightness += direction;
                if (brightness >= 50) {
                    brightness = 50;
                    direction = -4;
                } else if (brightness <= 5) {
                    brightness = 5;
                    direction = 4;
                }
                
                ws2812->SetBrightness(brightness);
                ws2812->SetPixel(0, WS2812::Color::CYAN);
            }, std::chrono::milliseconds(60), TaskPriority::TASKNORMAL, "led_ok");
            break;
            
        case kDeviceStateMqttOk:
            // 清除所有LED相关任务
            led_task_executor_->RemoveAllTasksByName("led_error");
            led_task_executor_->RemoveAllTasksByName("led_ok");
            // MQTT连接成功 - 青色常亮
            led_task_executor_->AddTask([ws2812]() {
                ws2812->SetBrightness(80);
                ws2812->SetPixel(0, WS2812::Color::CYAN);
            }, TaskType::IMMEDIATE, TaskPriority::TASKNORMAL, "led_ok");
            break;
            
        case kDeviceStateMqttError:
            break;
            
        case kDeviceStateOta:
            // 清除所有LED相关任务
            led_task_executor_->RemoveAllTasksByName("led_error");
            led_task_executor_->RemoveAllTasksByName("led_ok");
            break;


        case kDeviceStateOtaWrite:
            // 清除所有LED相关任务
            led_task_executor_->RemoveAllTasksByName("led_error");
            led_task_executor_->RemoveAllTasksByName("led_ok");
            // OTA更新中 - 青色呼吸灯
            led_task_executor_->AddPeriodicTask([ws2812]() {
                static uint8_t brightness = 5;
                static int8_t direction = 4;
                
                brightness += direction;
                if (brightness >= 50) {
                    brightness = 50;
                    direction = -4;
                } else if (brightness <= 5) {
                    brightness = 5;
                    direction = 4;
                }
                
                ws2812->SetBrightness(brightness);
                ws2812->SetPixel(0, WS2812::Color::CYAN);
            }, std::chrono::milliseconds(60), TaskPriority::TASKNORMAL, "led_ok");
            break;

            
        case kDeviceStateOtaError:
            break;
            
        case kDeviceStateError:
            // 系统错误状态 - 轮换显示所有存在的错误类型
            led_task_executor_->RemoveAllTasksByName("led_ok");
            {   
                // 检查错误标志是否发生变化
                static uint16_t last_error_flags = 0;
                if (last_error_flags == error_flags_) {
                    // 错误标志未变化，不需要重新创建LED任务
                    ESP_LOGI(TAG, "错误标志未变化(0x%04X)，保持当前LED轮换任务", error_flags_);
                    break;
                }
                
                // 错误标志发生变化，需要重新创建LED任务
                ESP_LOGI(TAG, "错误标志变化: 0x%04X -> 0x%04X，重新创建LED轮换任务", last_error_flags, error_flags_);
                last_error_flags = error_flags_;
                
                // 清除现有LED任务
                led_task_executor_->RemoveAllTasksByName("led_error");
                
                // 定义错误显示信息
                struct ErrorDisplayInfo {
                    ErrorFlags flag;
                    WS2812::Color color;
                    uint8_t blink_period;  // 闪烁周期（任务周期的倍数）
                    const char* name;
                };
                
                std::vector<ErrorDisplayInfo> active_errors;
                
                // 收集所有存在的错误类型
                if (HasError(ERROR_HARDWARE)) {
                    active_errors.push_back({ERROR_HARDWARE, WS2812::Color::RED, 1, "硬件错误"});  // 50ms = 1个周期
                }
                if (HasError(ERROR_WIFI)) {
                    active_errors.push_back({ERROR_WIFI, WS2812::Color::RED, 16, "WiFi错误"});     // 800ms = 16个周期
                }
                if (HasError(ERROR_MQTT)) {
                    active_errors.push_back({ERROR_MQTT, WS2812::Color::YELLOW, 1, "MQTT错误"});   // 50ms = 1个周期
                }
                if (HasError(ERROR_OTA)) {
                    active_errors.push_back({ERROR_OTA, WS2812::Color::PURPLE, 16, "OTA错误"});    // 800ms = 16个周期
                }
                
                if (!active_errors.empty()) {
                    // 错误轮换显示任务 - 统一50ms周期
                    // 用 mutable lambda 捕获局部变量，避免 static 变量导致的越界
                    led_task_executor_->AddPeriodicTask([ws2812, active_errors]() mutable {
                        size_t current_error_index = 0;
                        uint16_t display_counter = 0;
                        uint16_t blink_counter = 0;
                        bool led_on = false;

                        return [ws2812, active_errors, current_error_index, display_counter, blink_counter, led_on]() mutable {
                            const uint16_t DISPLAY_DURATION = 100; // 每个错误显示100个周期(5秒)
                            if (active_errors.empty()) return;
                            if (current_error_index >= active_errors.size()) current_error_index = 0;
                            const auto& current_error = active_errors[current_error_index];
                            if (blink_counter % current_error.blink_period == 0) {
                                led_on = !led_on;
                                ws2812->SetBrightness(led_on ? 50 : 0);
                                ws2812->SetPixel(0, led_on ? current_error.color : WS2812::Color::BLACK);
                            }
                            blink_counter++;
                            display_counter++;
                            if (display_counter >= DISPLAY_DURATION) {
                                ESP_LOGI("LED", "切换到下一个错误: %s", current_error.name);
                                display_counter = 0;
                                blink_counter = 0;
                                current_error_index = (current_error_index + 1) % active_errors.size();
                                led_on = false;
                            }
                        };
                    }(), std::chrono::milliseconds(50), TaskPriority::TASKNORMAL, "led_error");
                }
            }
            break;
            
        case kDeviceStateUnknown:
        default:
            // 清除所有LED相关任务
            led_task_executor_->RemoveAllTasksByName("led_error");
            led_task_executor_->RemoveAllTasksByName("led_ok");
            // 未知状态 - 红色常亮
            led_task_executor_->AddTask([ws2812]() {
                ws2812->SetBrightness(80);
                ws2812->SetPixel(0, WS2812::Color::RED);
            }, TaskType::IMMEDIATE, TaskPriority::TASKNORMAL, "led");
            break;
    }
}